package juc.blockqueue.delayqueue;

/**
 * @ClassName TaskScheduler
 * @PackageName juc.blockqueue.delayqueue
 * @projectName myThread
 * @Description 1. 定时任务调度
 * @Author games
 * @Date 2025/9/4 下午1:27
 * @Version 1.0
 */
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

class ScheduledTask implements Delayed {
    private static final AtomicLong sequencer = new AtomicLong(0);

    private final long sequenceNumber;
    private final long scheduledTime;
    private final Runnable task;

    public ScheduledTask(long delay, TimeUnit unit, Runnable task) {
        this.sequenceNumber = sequencer.getAndIncrement();
        this.scheduledTime = System.currentTimeMillis() + unit.toMillis(delay);
        this.task = task;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = scheduledTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed other) {
        if (other == this) {
            return 0;
        }
        if (other instanceof ScheduledTask) {
            ScheduledTask otherTask = (ScheduledTask) other;
            long diff = scheduledTime - otherTask.scheduledTime;
            if (diff < 0) {
                return -1;
            } else if (diff > 0) {
                return 1;
            } else if (sequenceNumber < otherTask.sequenceNumber) {
                return -1;
            } else if (sequenceNumber > otherTask.sequenceNumber) {
                return 1;
            } else {
                return 0;
            }
        }
        long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
        return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
    }

    public void run() {
        task.run();
    }
}

public class TaskScheduler {
    public static void main(String[] args) {
        DelayQueue<ScheduledTask> taskQueue = new DelayQueue<>();

        // 添加定时任务
        taskQueue.put(new ScheduledTask(5, TimeUnit.SECONDS, new Runnable() {
            @Override
            public void run() {
                System.out.println("Task 1 executed at " + System.currentTimeMillis());
            }
        }));

        taskQueue.put(new ScheduledTask(1, TimeUnit.SECONDS, () ->
                System.out.println("Task 2 executed at " + System.currentTimeMillis())));

        // 任务执行器
        new Thread(() -> {
            try {
                while (true) {
                    ScheduledTask task = taskQueue.take(); // 按到期时间顺序执行
                    task.run();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
}

